package com.yuwl.flowable.test;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yuwl
 * @description 任务分配-流程变量-表达式分配
 * @since 2024-01-24 10:17
 */
public class ProcessEngineTest2 {

    private ProcessEngine processEngine;

    /**
     * 创建ProcessEngine-硬编码
     */
    // @Before
    public void testProcessEngine() {
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC")
                .setJdbcUsername("root")
                .setJdbcPassword("123456")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        processEngine = cfg.buildProcessEngine();
    }

    /**
     * 创建ProcessEngine-默认配置文件 flowable.cfg.xml
     */
    @Before
    public void testProcessEngineDefault() {
        // 默认配置文件加载
        processEngine = ProcessEngines.getDefaultProcessEngine();
        //ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
        //processEngine = cfg.buildProcessEngine();

        // 自定义配置文件加载
        //ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("flowable.cfg.xml");
        //processEngine = cfg.buildProcessEngine();
    }

    /**
     * 部署流程定义
     */
    @Test
    public void testDeploy() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
                // 任务分配-流程变量-表达式分配
                .addClasspathResource("myHoliday0201.bpmn20.xml")
                .name("XXX请假流程")
                .category("请假")
                .tenantId("test0201")
                .deploy();
        System.out.println("deployment.getId() = " + deployment.getId());
        System.out.println("deployment.getName() = " + deployment.getName());
    }

    /**
     * 流程定义查看
     */
    @Test
    public void testDeployQuery() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId("57501")
                .singleResult();
        System.out.println("processDefinition.getId() = " + processDefinition.getId());
        // xml定义的process name
        System.out.println("processDefinition.getName() = " + processDefinition.getName());
        System.out.println("processDefinition.getDeploymentId() = " + processDefinition.getDeploymentId());
        System.out.println("processDefinition.getDescription() = " + processDefinition.getDescription());
    }

    /**
     * 启动流程实例
     */
    @Test
    public void testRunProcess() {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 发起流程参数
        Map<String, Object> vars = new HashMap<>();
        // 任务分配-流程变量-表达式分配
        vars.put("assignee1", "zhangsan");
        vars.put("assignee2", "lisi");
        // startProcessInstanceById id为processDefinitionId
        ProcessInstance holidayRequest = runtimeService.startProcessInstanceById("myHoliday0201:1:57504", vars);
        System.out.println("holidayRequest.getProcessDefinitionId() = " + holidayRequest.getProcessDefinitionId());
        System.out.println("holidayRequest.getId() = " + holidayRequest.getId());
        System.out.println("holidayRequest.getActivityId() = " + holidayRequest.getActivityId());
    }


    /**
     * 查看任务
     */
    @Test
    public void testQueryTask() {
        TaskService taskService = processEngine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionId("myHoliday0201:1:57504")
                .taskAssignee("lisi")
                .list();
        for (Task task : list) {
            System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());
            System.out.println("task.getId() = " + task.getId());
            System.out.println("task.getAssignee() = " + task.getAssignee());
            System.out.println("task.getName() = " + task.getName());
        }
    }

    /**
     * 完成任务
     */
    @Test
    public void testCompleteTask() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionId("myHoliday0201:1:57504")
                .taskAssignee("lisi")
                .singleResult();
        // 获取流程变量
        Map<String, Object> processVariables = task.getProcessVariables();
        for (String s : processVariables.keySet()) {
            System.out.println(s + ": " + processVariables.get(s));
        }
        // 改变流程变量
        processVariables.put("approved", true);
        processVariables.put("description", "不想上班了。。。");
        //Map<String, Object> vars = new HashMap<>();
        // xml定义的参数：${approved}
        //vars.put("approved", false); // 拒绝请假
        taskService.complete(task.getId(), processVariables);
    }

    /**
     * 挂起/激活-流程实例
     */
    @Test
    public void testSuspendProcessInstance() {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId("47501")
                .singleResult();
        if (processInstance.isSuspended()) {
            // 挂起状态，可激活
            runtimeService.activateProcessInstanceById("47501");
            System.out.println("流程实例已激活");
        } else {
            // 激活状态，可挂起，无法处理任务
            runtimeService.suspendProcessInstanceById("47501");
            System.out.println("流程实例已挂起");
        }
    }

    /**
     * 删除流程
     */
    @Test
    public void testDeleteProcess() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 当流程实例实例未启动时的删除方式
        // repositoryService.deleteDeployment("1");
        // 当流程实例已经启动了的删除方式，true表示级联删除流程实例
        repositoryService.deleteDeployment("35001", true);
    }

    /**
     * 挂起/激活流程
     */
    @Test
    public void testSuspendProcess() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId("myHolidayUI:1:45004")
                .singleResult();
        if (processDefinition.isSuspended()) {
            // 挂起状态，可激活
            System.out.println("激活流程定义");
            repositoryService.activateProcessDefinitionById("myHolidayUI:1:45004");
        } else {
            // 激活状态，可挂起
            // 挂起的流程不可发起流程实例
            System.out.println("挂起流程定义");
            repositoryService.suspendProcessDefinitionById("myHolidayUI:1:45004");
        }
    }

    /**
     * 查看历史信息
     */
    @Test
    public void testQueryHistory() {
        HistoryService historyService = processEngine.getHistoryService();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId("60001")
                .finished()
                .orderByHistoricActivityInstanceEndTime()
                .asc()
                .list();
        for (HistoricActivityInstance instance : list) {
            System.out.println(instance.getId() + " - " + instance.getActivityId() + " - "
                    + instance.getActivityName() + " - " + instance.getDurationInMillis() + "ms");
        }
    }

}
